package com.spiro.test.net.tcp.ssl.unidirectional;

import com.spiro.test.net.common.Configuration;

import javax.net.ssl.*;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.security.KeyStore;
import java.util.Date;

/**
 * Created by tz0643 on 2016/6/17.
 */
public class SSLTcpServer {

    private SSLServerSocket serverSocket = null;


    public void guest (Socket socket) {
        Thread t = new Thread(new ServiceHandler(socket));
        t.start();
    }

    public void start(int port,
                      String keyStoreFilename, String keyStorePwd)
            throws Exception {

        KeyStore serverKeyStore = KeyStore.getInstance("JKS");
        serverKeyStore.load(new FileInputStream(keyStoreFilename),
                keyStorePwd.toCharArray());

        KeyManagerFactory kmf = KeyManagerFactory.getInstance(
                KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(serverKeyStore, keyStorePwd.toCharArray());

        SSLContext sslContext = SSLContext.getInstance("TLSv1");
        sslContext.init(kmf.getKeyManagers(), null, null);

        try {
            SSLServerSocketFactory factory
                    = sslContext.getServerSocketFactory();
            InetAddress address = InetAddress.getByAddress(
                    new byte[]{(byte) 192, (byte) 168, 10, (byte) 188});
            serverSocket = (SSLServerSocket) factory.createServerSocket(port, 10, address);
            serverSocket.setNeedClientAuth(false);
        } catch (IOException e) {
            throw e;
        }

        while (true) {
            System.out.println("Server start, port -> " + port);
            guest(serverSocket.accept());
            System.out.println("Guest client");
        }
    }


    class ServiceHandler implements Runnable {

        private Socket socket = null;
        private BufferedReader reader = null;
        private PrintWriter writer = null;

        public ServiceHandler(Socket socket) {
            this.socket = socket;
        }

        public Socket getSocket() {
            return socket;
        }

        @Override
        public void run() {

            try {
                reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
                writer = new PrintWriter(this.socket.getOutputStream());

                String line = null;
                while ((line = reader.readLine()) != null) {

                    if ("close".equals(line)) {
                        break;
                    }

                    System.out.println("c -> " + line);
                    writer.println("Received, t - " + new Date().toString());
                    writer.flush();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException e) {
                    }
                }
                if (writer != null) {
                    writer.close();
                }

                if (this.socket != null) {
                    try {
                        this.socket.close();
                    } catch (IOException e) {
                    }
                }
            }
        }
    }

    public static void main(String[] args) {

        Configuration conf = Configuration.getInstance();

        try {
            conf.init();
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(-1);
        }

        String serverKeyStore
                = conf.getProperty("net.ssl.bidirectional.server.keystore");
        String serverKeyStorePwd
                = conf.getProperty("net.ssl.bidirectional.server.keystore.pwd");

        SSLTcpServer tcpServer = new SSLTcpServer();
        try {
            tcpServer.start(9000,
                    serverKeyStore,
                    serverKeyStorePwd);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
